using System;

namespace SmartMathLibrary
{
    /// <summary>
    /// Interface to implement a SimplePolynomial class.
    /// </summary>
    public interface ISimplePolynomial
    {
        /// <summary>
        /// Gets the degree of the polynomial.
        /// </summary>
        /// <value>The degree of the polynomial.</value>
        int Degree { get; }

        /// <summary>
        /// Gets or sets the polynomial coefficients.
        /// </summary>
        /// <value>The polynomial coefficients.</value>
        Double[] Coefficients { get; }

        /// <summary>
        /// Sets the coefficient of the specified rank to zero.
        /// </summary>
        /// <param name="rank">he rank where the coefficient should be set to zero.</param>
        void SetRankToZero(int rank);

        /// <summary>
        /// Rounds the coefficients of the polynomial.
        /// </summary>
        /// <param name="decimals">The decimal precision.</param>
        void RoundCoefficients(int decimals);

        /// <summary>
        /// Raises the specified power for each coefficient of the polynomial.
        /// </summary>
        /// <param name="power">The number to raises the power.</param>
        void PowCoefficients(double power);

        /// <summary>
        /// Raises the specified power of the polynomial.
        /// </summary>
        /// <param name="power">The specified power.</param>
        void Pow(int power);

        /// <summary>
        /// Calculates the square root of the coefficients of the polynomial.
        /// </summary>
        void SqrtCoefficients();

        /// <summary>
        ///  Calculates the root of the coefficients of the polynomial.
        /// </summary>
        /// <param name="root">The root.</param>
        void RootCoefficients(double root);

        /// <summary>
        /// Applies the log10 to every coefficient of the polynomial.
        /// </summary>
        void Log10Coefficients();

        /// <summary>
        /// Applies the log to every coefficient of the polynomial.
        /// </summary>
        void LogCoefficients();

        /// <summary>
        /// Applies a coefficient to the current polynomial.
        /// </summary>
        /// <param name="applyCoefficient">The to apply coefficient.</param>
        void ApplyCoefficient(double applyCoefficient);

        /// <summary>
        /// Sets the value at a specified rank.
        /// </summary>
        /// <param name="rank">The rank where the coefficient should be set.</param>
        /// <param name="value">The value of the coefficient.</param>
        void SetValueAtRank(int rank, double value);

        /// <summary>
        /// Adds the value at a specified rank.
        /// </summary>
        /// <param name="rank">The rank where the coefficient should be added.</param>
        /// <param name="value">The add value of the coefficient.</param>
        void AddValueAtRank(int rank, double value);

        /// <summary>
        /// Subtracts the value at a specified rank.
        /// </summary>
        /// <param name="rank">The rank where the coefficient should be subtract.</param>
        /// <param name="value">The substract value of the coefficient.</param>
        void SubtractValueAtRank(int rank, double value);

        /// <summary>
        /// Checks if the parameter for x is root of the polynomial.
        /// </summary>
        /// <param name="value">The value to check.</param>
        /// <returns>
        /// 	<c>true</c> if the specified value is root; otherwise, <c>false</c>.
        /// </returns>
        bool IsRoot(double value);

        /// <summary>
        /// Gets the coefficient at a special rank.
        /// </summary>
        /// <param name="rank">The rank.</param>
        /// <returns>The coefficient of the rank.</returns>
        double ValueAtRank(int rank);

        /// <summary>
        /// Multiplies the polynomial with a scalar.
        /// </summary>
        /// <param name="scalar">The scalar value.</param>
        void MultiplyWithScalar(int scalar);

        /// <summary>
        /// Multiplies the polynomial with a scalar.
        /// </summary>
        /// <param name="scalar">The scalar value.</param>
        void MultiplyWithScalar(double scalar);

        /// <summary>
        /// Divides the polynomial through scalar.
        /// </summary>
        /// <param name="scalar">The scalar value.</param>
        void DivideWithScalar(int scalar);

        /// <summary>
        /// Divides the polynomial through scalar.
        /// </summary>
        /// <param name="scalar">The scalar value.</param>
        void DivideWithScalar(double scalar);

        /// <summary>
        /// Calculates one root of the polynomial by using the Newton-Raphson method.
        /// </summary>
        /// <param name="startvalue">The start value.</param>
        /// <param name="iterations">The number of iterations for finding a root.</param>
        /// <returns>One root of the polynomial.</returns>
        double FindRoot(double startvalue, int iterations);

        /// <summary>
        /// Creates the first derivative of the polynomial.
        /// </summary>
        /// <returns>Returns the derivative of the polynomial.</returns>
        SimplePolynomial Derivative();

        /// <summary>
        /// Normalizes the polynomial.
        /// </summary>
        void Normalize();

        /// <summary>
        /// Use Horner's method to compute and return the polynomial evaluated at x.
        /// </summary>
        /// <param name="x">The x value.</param>
        /// <returns>The evaluated value of the polynomial.</returns>
        double Evaluate(int x);

        /// <summary>
        /// Calculates the polynomial with a specified x number.
        /// </summary>
        /// <param name="x">The x value.</param>
        /// <returns>Returns the absolute value of the polynomial.</returns>
        double SolveAt(double x);

        /// <summary>
        /// Checks if the polynomial is a Zero Polynomial.
        /// </summary>
        /// <returns>
        /// 	<c>true</c> if this polynomial is zero; otherwise, <c>false</c>.
        /// </returns>
        bool IsZero();

        /// <summary>
        /// Removes the leading zeros of the polynomial.
        /// </summary>
        void RemoveLeadingZeros();

        /// <summary>
        /// Gets the coefficient of lowest exponent.
        /// </summary>
        /// <returns>Returns the coefficient of lowest exponent.</returns>
        double GetCoefficientOfLowestExponent();

        /// <summary>
        /// Gets the coefficient of biggest exponent.
        /// </summary>
        /// <returns>Returns the coefficient of biggest exponent.</returns>
        double GetCoefficientOfBiggestExponent();

        /// <summary>
        /// Gets the biggest coefficient of the polynomial.
        /// </summary>
        /// <returns>The biggest coefficient of the polynomial.</returns>
        double GetBiggestCoefficient();

        /// <summary>
        /// Gets smallest coefficient of the polynomial.
        /// </summary>
        /// <returns>The smallest coefficient of the polynomial.</returns>
        double GetSmallestCoefficient();

        /// <summary>
        /// Shifts the polynomial coefficients one to the left.
        /// </summary>
        void ShiftLeft();

        /// <summary>
        /// Shifts the polynomial coefficients n-times to the left. If the time parameter is
        /// negative it will execute the ShiftRight method. 
        /// </summary>
        /// <param name="times">The times to shift.</param>
        void ShiftLeft(int times);

        /// <summary>
        /// Shifts the polynomial coefficients one to the right.
        /// </summary>
        void ShiftRight();

        /// <summary>
        /// Shifts the polynomial coefficients n-times to the right. If the time parameter is
        /// negative it will execute the ShiftLeft method. 
        /// </summary>
        /// <param name="times">The times to shift.</param>
        void ShiftRight(int times);

        /// <summary>
        /// Makes a copy of the current polynomial.
        /// </summary>
        /// <returns>Returns a copy of the current polynomial</returns>
        SimplePolynomial Copy();

        /// <summary>
        /// Converts a SimplePolynomial to a Polynomial.
        /// </summary>
        /// <returns>The converted polynomial.</returns>
        Polynomial ToPolynomial();

        /// <summary>
        /// Converts the polynomial to a complex polynomial.
        /// </summary>
        /// <returns>The converted complex polynomial.</returns>
        ComplexPolynomial ToComplexPolynomial();

        /// <summary>
        /// Converts the polynomial to a rational polynomial.
        /// </summary>
        /// <returns>The converted rational polynomial.</returns>
        SimpleRationalPolynomial ToRationalPolynomial();
    }
}